package com.gaohui.nestedrecyclerview.java.view;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import com.gaohui.nestedrecyclerview.UIUtils;
import com.gaohui.nestedrecyclerview.java.adapter.MultiTypeAdapter;
import com.gaohui.nestedrecyclerview.java.utils.FlingHelper;

import java.util.concurrent.atomic.AtomicBoolean;

public class ParentRecyclerView extends RecyclerView {
    FlingHelper mFlingHelper;

    int mMaxDistance = 0;
    /**
     * 记录当前滑动的y轴加速度
     */
    int velocityY = 0;
    /**
     * 记录上次Event事件的y坐标
     */
    Float lastY = 0f;
    int mTotalDy = 0;
    /**
     * 用于判断RecyclerView是否在fling
     */
    boolean isStartFling = false;

    /**
     * 当前是否能上下滑动
     */
    private AtomicBoolean mCanScrollVertically;
    private ParentRvListener mParentRvListener;

    private void init(Context context) {
        mFlingHelper = new FlingHelper(context);
        mMaxDistance = mFlingHelper.getVelocityByDistance((double) (UIUtils.getScreenHeight() * 4));
        mCanScrollVertically = new AtomicBoolean(true);

        //监听外层RV滑动, 如果到底部了,则将滑动事件交给子RV
        addOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
                //如果父RecyclerView fling过程中已经到底部，需要让子RecyclerView滑动神域的fling
                if (newState == SCROLL_STATE_IDLE) {
                    dispatchChildFling();
                }

                /*//当前RecyclerView显示出来的最后一个的item的position
                int lastPosition = -1;
                //当前状态为停止滑动状态SCROLL_STATE_IDLE时
                if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
                    if (layoutManager instanceof GridLayoutManager) {
                        //通过LayoutManager找到当前显示的最后的item的position
                        lastPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
                    } else if (layoutManager instanceof LinearLayoutManager) {
                        lastPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
                    }

                    //时判断界面显示的最后item的position是否等于itemCount总数-1也就是最后一个item的position
                    //如果相等则说明已经滑动到最后了
                    if (lastPosition == recyclerView.getLayoutManager().getItemCount() - 1) {
                        if (mParentRvListener != null) {
                            mParentRvListener.onScrollEnd();
                        }
                    }

                }*/
            }

            @Override
            public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                if (isStartFling) {
                    mTotalDy = 0;
                    isStartFling = false;
                }
                //记录当前RecyclerView在y轴的偏移
                mTotalDy += dy;

                //得到当前显示的最后一个item的view
                View lastChildView = recyclerView.getLayoutManager().getChildAt(recyclerView.getLayoutManager().getChildCount() - 1);
                //得到lastChildView的bottom坐标值
                int lastChildBottom = lastChildView.getBottom();
                //得到Recyclerview的底部坐标减去底部padding值，也就是显示内容最底部的坐标
                int recyclerBottom = recyclerView.getBottom() - recyclerView.getPaddingBottom();
                //通过这个lastChildView得到这个view当前的position值
                int lastPosition = recyclerView.getLayoutManager().getPosition(lastChildView);

                //判断lastChildView的bottom值跟recyclerBottom
                //判断lastPosition是不是最后一个position
                //如果两个条件都满足则说明是真正的滑动到了底部
                if (lastChildBottom == recyclerBottom && lastPosition == recyclerView.getLayoutManager().getItemCount() - 1) {
                    if (mParentRvListener != null) {
                        mParentRvListener.onScrollEnd();
                    }
                }

            }
        });

    }

    public void initLayoutManager(Context context) {
        LinearLayoutManager layoutManager = new LinearLayoutManager(context) {
            @Override
            public int scrollVerticallyBy(int dy, Recycler recycler, State state) {
                try {
                    return super.scrollVerticallyBy(dy, recycler, state);
                } catch (Exception e) {
                    e.printStackTrace();
                    return 0;
                }
            }

            @Override
            public void onLayoutChildren(Recycler recycler, State state) {
                try {
                    super.onLayoutChildren(recycler, state);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            /*@Override
            public boolean canScrollVertically() {
                ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
                return (canScrollVertically.get()  || childRecyclerView == null || childRecyclerView.isScrollTop());
            }*/

            @Override
            public boolean canScrollVertically() {
                ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
                if (childRecyclerView != null && !childRecyclerView.isScrollTop()) {
                    return false;
                } else {
                    return mCanScrollVertically.get();
                }
            }

            @Override
            public void addDisappearingView(View child) {
                try {
                    super.addDisappearingView(child);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            @Override
            public boolean supportsPredictiveItemAnimations() {
                return false;
            }
        };

        layoutManager.setOrientation(VERTICAL);
        setLayoutManager(layoutManager);
    }

    private int startX, startY;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) {
            //ACTION_DOWN的时候重置加速度
            velocityY = 0;
            stopScroll();
        }
        if (!(ev == null || ev.getAction() == MotionEvent.ACTION_MOVE)) {
            //在非ACTION_MOVE的情况下，将lastY置为0
            lastY = 0f;
        }

        //todo xfhy 未验证
        if (ev != null) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startX = (int) ev.getX();
                    startY = (int) ev.getY();
                    getParent().requestDisallowInterceptTouchEvent(true);
                    break;
                case MotionEvent.ACTION_MOVE:
                    int endX = (int) ev.getX();
                    int endY = (int) ev.getY();

                    //当前手指正在触摸的view
                    View childViewUnder = findChildViewUnder(endX, endY);

                    if (childViewUnder != null) {
                        Log.d("xfhy", "view is " + childViewUnder.getClass().getName());
                    }

                    if (childViewUnder instanceof InforLinearLayout) {
                        getParent().requestDisallowInterceptTouchEvent(true);
                    } else {
                        int disX = Math.abs(endX - startX);
                        int disY = Math.abs(endY - startY);
                        if (disX > disY) {
                            //如果是纵向滑动，告知父布局不进行事件拦截，交由子布局消费，　requestDisallowInterceptTouchEvent(true)
                            //requestDisallowInterceptTouchEvent具有传递性
                            //找出当前滑动的这个地方的View，如果是横向的RecycleView，则禁止ViewPager2滑动
                            if (childViewUnder instanceof RecyclerView) {
                                RecyclerView recyclerView = (RecyclerView) childViewUnder;
                                LayoutManager layoutManager = recyclerView.getLayoutManager();
                                if (layoutManager instanceof LinearLayoutManager) {
                                    LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
                                    //横向滑动
                                    if (linearLayoutManager.getOrientation() == LinearLayoutManager.HORIZONTAL) {
                                        Log.d("xfhy", "view is 这是横向滑动的RV");
                                        getParent().requestDisallowInterceptTouchEvent(true);
                                    } else {
                                        getParent().requestDisallowInterceptTouchEvent(false);
                                    }
                                } else {
                                    getParent().requestDisallowInterceptTouchEvent(false);
                                }
                            } else {
                                getParent().requestDisallowInterceptTouchEvent(false);
                            }
                        } else {
                            getParent().requestDisallowInterceptTouchEvent(false);
                        }
                    }
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    getParent().requestDisallowInterceptTouchEvent(false);
                    break;
                default:
                    break;
            }
        }

        try {
            return super.dispatchTouchEvent(ev);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        if (lastY == 0f) {
            lastY = e.getY();
        }
        if (isScrollEnd()) {
            //如果父RecyclerView已经滑动到底部，需要让子RecyclerView滑动剩余的距离
            ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
            if (childRecyclerView != null) {
                int deltaY = (int) (lastY - e.getY());
                mCanScrollVertically.set(false);
                childRecyclerView.scrollBy(0, deltaY);
            }
        }
        if (e.getAction() == MotionEvent.ACTION_UP && isChildRecyclerViewCanScrollUp()) {
            mCanScrollVertically.set(true);
        }
        lastY = e.getY();
        try {
            return super.onTouchEvent(e);
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean fling(int velx, int velY) {
        boolean fling = super.fling(velx, velY);
        if (!fling || velY <= 0) {
            velocityY = 0;
        } else {
            isStartFling = true;
            velocityY = velY;
        }
        return fling;
    }

    private void dispatchChildFling() {
        //滑动到底部并且y轴加速度不为0
        if (isScrollEnd() && velocityY != 0) {
            double splineFlingDistance = mFlingHelper.getSplineFlingDistance(velocityY);
            if (splineFlingDistance > mTotalDy) {
                childFling(mFlingHelper.getVelocityByDistance(splineFlingDistance - mTotalDy));
            }
        }
        mTotalDy = 0;
        velocityY = 0;
    }

    private void childFling(int velocityByDistance) {
        ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
        if (childRecyclerView != null) {
            childRecyclerView.fling(0, velocityByDistance);
        }
    }

    /**
     * 找当前正在展示的RecyclerView
     */
    private ChildRecyclerView findNestedScrollingChildRecyclerView() {
        if (getAdapter() != null && (getAdapter() instanceof MultiTypeAdapter)) {
            return ((MultiTypeAdapter) getAdapter()).getCurrentChildRecyclerView();
        }
        return null;
    }

    private boolean isScrollEnd() {
        //RecyclerView.canScrollVertically(1)的值表示是否能向上滚动，false表示已经滚动到底部
        boolean result = !canScrollVertically(1);
        Log.d("xfhy_scroll", "isScrollEnd() = " + result);
        return result;
    }

    @Override
    public void scrollToPosition(final int position) {
        ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
        if (childRecyclerView != null) {
            childRecyclerView.scrollToPosition(position);
        }
        postDelayed(new Runnable() {
            @Override
            public void run() {
                ParentRecyclerView.super.scrollToPosition(position);
            }
        }, 50);
    }

    @Override
    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
        return (target != null) && (target instanceof ChildRecyclerView);
    }

    @Override
    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
        ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
        //1.当前Parent RecyclerView没有滑动底，且dy> 0 是下滑
        boolean isParentCanScroll = dy > 0 && !isScrollEnd();
        //2.当前Child RecyclerView滑到顶部了，且dy < 0,即上滑
        boolean isChildCanNotScroll = !(dy >= 0
                || childRecyclerView == null
                || !childRecyclerView.isScrollTop());
        //以上两种情况都需要让Parent RecyclerView去scroll，和下面onNestedPreFling机制类似
        if (isParentCanScroll /*|| isChildCanNotScroll*/) {
            scrollBy(0, dy);
            consumed[1] = dy;
        }
    }

    @Override
    public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
        return true;
    }

    @Override
    public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
        ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
        boolean isParentCanFling = velocityY > 0f && !isScrollEnd();
        boolean isChildCanNotFling = !(velocityY >= 0
                || childRecyclerView == null
                || !childRecyclerView.isScrollTop());

        if (!isParentCanFling /*&& !isChildCanNotFling*/) {
            return false;
        }
        fling(0, (int) velocityY);
        return true;
    }

    /**
     * 子RV是否还能继续向上滑动
     */
    public boolean isChildRecyclerViewCanScrollUp() {
        ChildRecyclerView childRecyclerView = findNestedScrollingChildRecyclerView();
        if (childRecyclerView != null) {
            return !childRecyclerView.isScrollTop();
        }
        return false;
    }

    public void setCanScrollVertically(boolean canScrollVertically) {
        this.mCanScrollVertically.set(canScrollVertically);
    }

    public void setParentRvListener(ParentRvListener mParentRvListener) {
        this.mParentRvListener = mParentRvListener;
    }

    public interface ParentRvListener {
        /**
         * 滑动至底部时
         */
        void onScrollEnd();
    }

    public ParentRecyclerView(@NonNull Context context) {
        super(context);
        init(context);
    }

    public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public ParentRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

}
